/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package image.edge;

import image.processing.ImageProcessor;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import mask.ImageMask;

/**
 *
 * @author tommy
 */
public class SobelEdgeDetector extends EdgeDetectorImpl {
	private ImageMask horzDerivativeMask, vertDerivativeMask;
	
	public SobelEdgeDetector (BufferedImage src) {
		super(src);
		double[][] horzSobelOperator = {
		  { -1d, 0d, 1d },
		  { -2d, 0d, 2d },
		  { -1d, 0d, 1d },
		};
		
		double[][] vertSobelOperator = {
			{-1d,-2d,-1d},
			{ 0d, 0d, 0d },
			{1d, 2d, 1d }
		};
		this.horzDerivativeMask = new ImageMask(horzSobelOperator, 3);
		this.vertDerivativeMask = new ImageMask(vertSobelOperator, 3);
	}
	
	public BufferedImage FindEdges() {
		double[] gradientMagnitudes;
		Double[] gdx, gdy;
		double max, ratio;
		
		WritableRaster outRaster;
		Raster inRaster;

		// Only intensity (grey-scale) images supported for the time being
		if (src.getType() != BufferedImage.TYPE_BYTE_GRAY) {
			return null;
		}
		
		gradientMagnitudes = new double[ret.getHeight()*ret.getWidth()];
		// get original image pixels
		inRaster = src.getData();
		
		// Applies Sobel Operator to find gradient levels for each intensity pixel!
		// does not process padded border edge
		gdx = horzDerivativeMask.applyMask(src);
		gdy = vertDerivativeMask.applyMask(src);
		max = Double.MIN_VALUE;
		
		for (int i = 0 ; i < gradientMagnitudes.length ; i++) {
			gradientMagnitudes[i] = Math.sqrt(gdx[i]*gdx[i] + gdy[i]*gdy[i]);
			
			if (gradientMagnitudes[i] > max) {
				max = gradientMagnitudes[i];
			}
		}
		
		ratio = max/255d;
		
		outRaster = ret.getRaster();

		// builds image based on sobel gradient magnitude
		for (int y = 0 ; y < ret.getHeight() ; y++) {
			for (int x = 0 ; x < ret.getWidth() ; x++) {
				outRaster.setSample(x, y, 0, (int)(gradientMagnitudes[y*ret.getWidth() + x]/ratio));
			}
		}
		return ret;
	}
}
